package com.example.readfile

import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.SharedPreferences
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.os.RemoteException
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.ComponentActivity
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.cloudplay.messagesdk.MessageSDK
import com.cloudplay.messagesdk.listener.MessageHandler
import com.google.gson.Gson
import com.google.gson.JsonParser
import com.haima.agentpartner.AccountInfoMessage
import com.haima.agentpartner.DeviceInfo
import com.haima.agentpartner.DeviceInfoMessage
import com.haima.agentpartner.HaimaMiddlewareBean
import com.haima.agentpartner.HaimaMiddlewareResponse
import com.haima.agentpartner.IMiddlewareRequest
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
import com.yechaoa.yutilskt.BuildConfig
import com.yechaoa.yutilskt.YUtils
import fuck.hookwzry.qq.FileRead
import org.json.JSONException
import org.jsoup.Connection
import org.jsoup.Jsoup

class AuthActivity : ComponentActivity() {

    private val TAG = AuthActivity::class.java.simpleName
    private val NEED_TOAST: Boolean = false

    /**<授权方式>**/
    private var authType: AuthLoginType? = null

    /**<是否已经绑定服务>**/
    private var mIsBound = false

    /**<中间件>**/
    private var middlewareRequest: IMiddlewareRequest? = null

    /**<设备信息>**/
    private var mDevice: DeviceInfo? = null

    /**<账号信息>**/
    private var mAccount: AccountInfoMessage? = null

    /**<点击次数>**/
    private var clickCount = 0

    /**<定时>**/
    private val handler: Handler = Handler(Looper.getMainLooper())

    /**
     * bindService连接成功后
     */
    private val connection: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            Log.d(TAG, "连接中..")
            try {
                middlewareRequest = IMiddlewareRequest.Stub.asInterface(service)
                Log.d(TAG, "连接 Middleware 服务，开始监听请求")
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
        }

        override fun onServiceDisconnected(name: ComponentName) {
            Log.d(TAG, "断开连接..")
            middlewareRequest = null
        }
    }

    private var videoPlayer: CustomGSYVideoPlayer? = null

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_auth)

        // 消息SDK初始化
        initMessageSDK()
        // 绑定服务
        bindBoundService()
        // 设置文字
        configTextView()
        // 设置点击
        setupButtonActions()
        // 设置播放器
        setupPlayer()
        // 设置调试模式
        setupDebugModel()
    }


    private fun testPostAuthorization() {
        val jsonStr = """
        {
            "qimei":"8055de8648c5c3f5d59d8dda10001b11960c",
            "qq":"2628980010",
            "ticket":{
                "qq":2628980010,
                "tgt":"05d3155fe547980402c32decfc3b6b29ec67df1387482c68aa78ab6dcecdc16912182372e31ce026d432ddda82cee860ec1f02442cf073f6df8f14813fdcbfa4eae5c09abb5c6b84",
                "d2Key":"2c59695b74595d6d4150636b29604525",
                "tgtKey":"726b33557a234d7829674e2953653245",
                "d2":"7b3ec4b1e4d4361dfe511b78d43a130e2cf17de703a4969fd8ed86223153ae77b7cf1422a33eb7d836860f2dd4a90bfc9219382b7a9523c00db77943daa2d0a714ac6a094cfdc64306ec6408c3a581b4316fab3b1b576c24",
                "deviceToken":""
            },
            "appid":1104466820,
            "imei":"568925de460bdf37",
            "guid":"6655529f59f72f2b33e7082369c238a0",
            "model":"Kona for arm64",
            "brand":"qti",
            "androidId":"568925de460bdf37",
            "key":"zerPob3P12IPjf5lBWKtVffu"
        }
    """.trimIndent()

        Thread {
            Log.d(TAG, "测试请求")
            val jsonObject = JSON.parseObject(jsonStr)
            postAuthorization(jsonObject)
        }.start()
    }

    /**
     * 点击登录完成
     *
     * 检查文件夹权限并申请权限
     */
    private fun checkRootPermission() {
        YUtils.showLoading(this, "授权中...")
        val hasPermissions = FileRead.hasReadAndWritePermissions(this@AuthActivity, NEED_TOAST)
        if (!hasPermissions) {
            YUtils.hideLoading()
            sendMessage("没有Root权限，去申请权限")
            getRootPermission()
        } else {
            handMobileTokenValue()
        }
    }

    /**
     * 获取文件夹的root权限
     */
    private fun getRootPermission() {
        val result = FileRead.getRootPermission(this, NEED_TOAST)
        if (result.success) {
            handMobileTokenValue()
        } else {
            YUtils.hideLoading()
            sendMessage("文件Root权限获取失败：" + result.message)
        }
    }

    /**
     * 点击登录完成
     *
     * 开始处理登录态文件
     */
    private fun handMobileTokenValue() {
        // 读取IMEI
        val imei = FileRead.readQimei(this@AuthActivity, NEED_TOAST)
        if (imei.isNullOrEmpty()) {
            YUtils.hideLoading()
            Toast.makeText(this, "请先登录QQ", Toast.LENGTH_SHORT).show()
            return
        }
        sendMessage("拿到了imei，imei=$imei")

        // 读取Guide
        val guide = FileRead.readGuid(this@AuthActivity, NEED_TOAST)
        if (guide.isNullOrEmpty()) {
            YUtils.hideLoading()
            Toast.makeText(this, "请先登录QQ", Toast.LENGTH_SHORT).show()
            return
        }
        sendMessage("拿到了guide，guide=$guide")

        // 获取Ticket
        val ticket = FileRead.getTk(this@AuthActivity, guide, NEED_TOAST)
        if (ticket.isNullOrEmpty()) {
            YUtils.hideLoading()
            Toast.makeText(this, "请先登录QQ", Toast.LENGTH_SHORT).show()
            return
        }
        sendMessage("拿到了ticket，ticket=$ticket")
        sendMessage("拿到了所有登录态文件，开始解密授权操作...")

        // 登录成功了
        // 直接去授权[默认授权王者]
        mDevice?.let { device ->
            if (device.gameName.contains("王者荣耀")) {
                authType = AuthLoginType.WZ
                handleAuthorization(1104466820L, imei, guide, ticket)
                sendMessage("当前授权的是：AuthLoginType.WZ")
            } else if (device.gameName.contains("和平精英")) {
                authType = AuthLoginType.HP
                handleAuthorization(1106467070L, imei, guide, ticket)
                sendMessage("当前授权的是：AuthLoginType.HP")
            } else if (device.gameName.contains("火影忍者")) {
                authType = AuthLoginType.HY
                handleAuthorization(1104307008L, imei, guide, ticket)
                sendMessage("当前授权的是：AuthLoginType.HY")
            } else {
                sendMessage("游戏错误！")
            }
        } ?: sendMessage("准备授权时，设备信息异常")
    }

    /**
     * 绑定服务
     */
    private fun bindBoundService() {
        try {
            mIsBound = bindService()
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 绑定服务
     *
     * @return service
     */
    private fun bindService(): Boolean {
        val intent = Intent()
        intent.setAction("com.android.agent.partner.MIDDLEWARE_REQUEST")
        intent.setPackage("com.android.agent.partner")
        return bindService(intent, connection, BIND_AUTO_CREATE)
    }

    /**
     * 设置文字
     */
    private fun configTextView() {
        val tvInstruction: TextView = findViewById(R.id.tv_instruction)

        val text = "点击“去授权”按钮将会直接跳转至QQ登录页面，您正常登录QQ即可。" +
                "\n\n登录成功后，请点击下方“授权成功”按钮。" +
                "\n\n在登录过程中，您可能会遇到滑块验证或需要输入手机号验证码的情况，请您及时配合以确保流程顺畅。" +
                "\n\n请注意，授权成功后，为了保障您的账号安全及授权的有效性，请避免在其他任何设备上再次登录该QQ账号，以免导致授权失效。"
        val spannableString = SpannableString(text)

        // 设置多个关键字为红色
        val keywords = listOf(
            "QQ登录页面",
            "滑块验证或需要输入手机号验证码的情况",
            "请避免在其他任何设备上再次登录该QQ账号"
        )
        for (keyword in keywords) {
            val start = text.indexOf(keyword)
            if (start >= 0) {
                val end = start + keyword.length
                spannableString.setSpan(
                    ForegroundColorSpan(Color.RED),
                    start,
                    end,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                )
            }
        }
        tvInstruction.text = spannableString
    }

    /**
     * 测试模式
     * 设置按钮点击
     */
    @SuppressLint("SetTextI18n")
    private fun setupButtonActions() {
        // 打开QQ---->【打开云游戏->云游戏授权QQ登录，登陆成功后再进行授权】---> 去授权按钮
        val btnSubmit = findViewById<Button>(R.id.goAuth)
        btnSubmit.setOnClickListener {
            Log.d(TAG, "打开 QQ")
            openMobileQQ()
//            testPostAuthorization()
        }


        // 登录完成----> 授权成功按钮
        val btnChmod = findViewById<Button>(R.id.authSuccess)
        btnChmod.setOnClickListener {
            checkRootPermission()
        }
    }

    /**
     * 设置播放器
     */
    private fun setupPlayer() {
        videoPlayer = findViewById(R.id.video_player)

        val videoUrl = "https://res.playfuncat.cn/tanwanmao/47669_1716952900.mp4"
        videoPlayer?.setUp(videoUrl, true, "自动授权教程")

        // 隐藏返回按钮
        videoPlayer?.backButton?.visibility = View.GONE

        // 设置封面图
        val imageView = ImageView(this)
        imageView.scaleType = ImageView.ScaleType.CENTER_CROP
        videoPlayer?.thumbImageView = imageView

        // 启动播放
        videoPlayer?.startPlayLogic()

        // 设置全屏按键功能
        videoPlayer?.fullscreenButton?.setOnClickListener { v ->
            // 全屏点击处理
            resolveFullBtn(videoPlayer!!)
        }
    }

    /**
     * 全屏按钮点击
     *
     * @param standardGSYVideoPlayer
     */
    private fun resolveFullBtn(standardGSYVideoPlayer: StandardGSYVideoPlayer) {
        standardGSYVideoPlayer.startWindowFullscreen(this, true, true)
    }

    /**
     * Debug点击模式
     */
    private fun setupDebugModel() {
        val topBanner = findViewById<ImageView>(R.id.topBanner)

        topBanner.setOnClickListener {
            clickCount++
            if (clickCount == 1) {
                handler.postDelayed({ clickCount = 0 }, 2000) // Reset count after 2 seconds
            }
            if (clickCount == 5) {
                clickCount = 0
                showDebugDialog()
            }
        }
    }

    private fun showDebugDialog() {
        AlertDialog.Builder(this)
            .setTitle("调试模式")
            .setMessage("是否进入调试模式?")
            .setPositiveButton("确认") { dialog, which ->
                val intent: Intent = Intent(this@AuthActivity, DebugActivity::class.java)
                startActivity(intent)
            }
            .setNegativeButton("取消", null)
            .show()
    }

    /**
     * 打开QQ
     */
    private fun openMobileQQ() {
        try {
            YUtils.showLoading(this, "启动中...")
            val uri = Uri.parse("mqqwpa://im/login?style=4")
            val intent = Intent(Intent.ACTION_VIEW, uri)
            startActivity(intent)
        } catch (e: ActivityNotFoundException) {
            YUtils.hideLoading()
            // QQ客户端没有安装
            Toast.makeText(this, "未安装QQ或找不到QQ", Toast.LENGTH_SHORT).show()
        }
    }

    /**
     * 中间件与客户端交互的SDK初始化
     */
    @SuppressLint("SetTextI18n")
    private fun initMessageSDK() {
        val messageSDK = MessageSDK.getInstance()
        messageSDK.setDebug(BuildConfig.DEBUG)
        messageSDK.init(this, "com.tencent.mobileqq")

        sendMessage("初始化MessageSDK")

        Log.d(TAG, "开始初始化MessageSDK = ${messageSDK.configInfo}")
        Log.d(TAG, "isRunningCloud = ${messageSDK.isRunningCloud}")

        // 监控消息
        val messageHandler = object : MessageHandler {

            // 收到二进制消息
            override fun onBinaryMessage(bytes: ByteArray) {
                Log.d(TAG, "onBinaryMessage: ${String(bytes)}")
            }

            // 收到普通text消息
            override fun onTextMessage(payload: String) {
                Log.d(TAG, "onTextMessage: $payload")

                // 设备信息
                try {
                    val gson = Gson()
                    val jsonObject = JsonParser.parseString(payload).asJsonObject
                    val method = jsonObject["method"]?.asString

                    when (method) {
                        "accInfo" -> {
                            val accMessage = gson.fromJson(payload, AccountInfoMessage::class.java)
                            logAccountInfo(accMessage)
                            sendMessage("收到accInfo：${accMessage.toString()}")
                        }

                        "deviceInfo" -> {
                            val deviceInfoMessage = gson.fromJson(payload, DeviceInfoMessage::class.java)
                            val device = deviceInfoMessage.data
                            if (device.gameName != null) {
                                logDeviceInfo(device)
                                setDeviceInfo()
                            }
                            sendMessage("收到deviceInfo：${device.toString()}")
                        }

                        "useHaiMaDeviceInfo" -> {
                            getDeviceInfo()
                            sendMessage("收到useHaiMaDeviceInfo")
                        }
                    }
                } catch (e: Exception) {
                    Log.e(TAG, "Failed to parse message", e)
                }
            }
        }

        messageSDK.setMessageHandler(messageHandler)
    }

    /**
     * 登录的账密（后续用于Xposed自动输入）
     *
     * @param accMessage
     */
    @SuppressLint("CommitPrefEdits")
    private fun logAccountInfo(accMessage: AccountInfoMessage) {
        Log.d(TAG, "Method: ${accMessage.method}")
        Log.d(TAG, "Channel: ${accMessage.channel}")
        Log.d(TAG, "Acc: ${accMessage.data.acc}")
        Log.d(TAG, "Pwd: ${accMessage.data.pwd}")
        Log.d(TAG, "GameName: ${accMessage.data.gameName}")
        this.mAccount = accMessage

        sendMessage("收到账号信息和游戏信息：${accMessage.toString()}")

        // 保存
        val sharedPreferences: SharedPreferences = this.getSharedPreferences("com.example.readfile", Context.MODE_PRIVATE)
        val editor = sharedPreferences.edit()
        editor.putString("account", accMessage.data.acc)
        editor.putString("password", accMessage.data.pwd)
        editor.apply()
    }

    /**
     * 外部传入的设备信息[Android 和 iOS]
     * H5 获取不到设备信息，所以就获取海马云的设备信息
     *
     * @param device
     */
    private fun logDeviceInfo(device: DeviceInfo) {
        Log.d(TAG, "Model: ${device.model}")
        Log.d(TAG, "Brand: ${device.brand}")
        Log.d(TAG, "GameName: ${device.gameName}")
        this.mDevice = device
    }

    /**
     * 注销SDK
     */
    private fun unInitMessageSDK() {
        MessageSDK.getInstance().stop()
    }

    /**
     * 发送消息
     *
     * @param msgContent 消息内容
     */
    private fun sendMessage(msgContent: String) {
        val mId = MessageSDK.getInstance().sendMessage(msgContent) { success, messageId ->
            val sendResult = "发送文本消息: msg:$msgContent, mId:$messageId,result:$success"
            Log.d(TAG, sendResult)
        }
        Log.d(TAG, "发送消息后的 messageId:$mId")
    }

    /**
     * 授权结果
     * 先要检测登录态文件是否存在
     */
    @SuppressLint("SetTextI18n")
    private fun handleAuthorization(appId: Long, imei: String, guide: String, tkk: JSONObject) {
        sendMessage("start")
        Thread {
            try {
                try {
                    // 将JSON字符串解析为JSONObject
                    val jsonObject: JSONObject = JSON.parseObject(tkk.toString())
                    processAuthorization(imei, guide, jsonObject, appId)
                } catch (e: Exception) {
                    YUtils.hideLoading()
                    println("Error parsing JSON: ${e.message}")
                    sendMessage("处理 JSON错误: ${e.message}")
                }
            } catch (e: Exception) {
                YUtils.hideLoading()
                println("Error parsing JSON: ${e.message}")
                sendMessage("处理 JSON错误: ${e.message}")
            }
        }.start()
    }

    /**
     * 开始授权
     */
    private fun processAuthorization(qimei: String, guid: String, ticket: JSONObject, appId: Long) {
        val spreadData = JSON.parseObject(qimei).getJSONObject("spreadData")
        val data = spreadData.getJSONObject(ArrayList(spreadData.keys)[0])
        mDevice?.let {
            val jsonObject = JSONObject().apply {
                put("appid", appId)
                put("model", it.model)
                put("brand", it.brand)
                put("imei", data.getString("aid"))
                put("androidId", data.getString("aid"))
                put("qimei", data.getString("q16"))
                put("guid", guid)

                put("qq", ticket.getString("qq"))
                put("ticket", ticket)

                // 王者多一个参数
                if (authType == AuthLoginType.WZ) {
                    put("key", "zerPob3P12IPjf5lBWKtVffu")
                }
            }
            sendMessage("开始预请求: ${jsonObject.toJSONString()}")
            postAuthorization(jsonObject)
        } ?: sendMessage("开始授权时，设备信息异常")
    }

    /**
     * 发送请求
     */
    @SuppressLint("SetTextI18n")
    private fun postAuthorization(jsonObject: JSONObject) {
        Log.d(TAG, "开始请求")

        try {
            val url = "$AUTH_BASEURL/mobile/saveDeviceInfo"
            val originalJsonStr = jsonObject.toJSONString()

            // 包装 param 参数
            val wrappedJson = JSONObject().apply {
                this["param"] = originalJsonStr
            }

            Log.d(TAG, "请求地址：$url")
            Log.d(TAG, "请求头：content-type=application/json;charset=UTF-8")
            Log.d(TAG, "请求体：$wrappedJson")

            val response = Jsoup.connect(url)
                .timeout(20000)
                .ignoreContentType(true)
                .ignoreHttpErrors(true)
                .header("content-type", "application/json;charset=UTF-8")
                .method(Connection.Method.POST)
                .requestBody(wrappedJson.toJSONString())
                .execute()

            val statusCode = response.statusCode()
            val body = response.body()

            Log.d(TAG, "响应状态码：$statusCode")
            Log.d(TAG, "响应体原文：$body")

            val obj = JSON.parseObject(body)
            val desc = obj?.getString("desc") ?: "无描述"

            sendMessage("授权请求结果：$body")
            runOnUiThread {
                YUtils.hideLoading()
                sendMessage("授权请求结果：$desc")
            }
        } catch (e: Exception) {
            YUtils.hideLoading()
            Log.e(TAG, "请求异常：${e.message}", e)
            runOnUiThread {
                sendMessage("请求异常：${e.localizedMessage}")
            }
        }
    }

    /**
     * 通过commonFunction
     * 设置设备信息
     */
    @SuppressLint("SetTextI18n")
    @Throws(RemoteException::class)
    private fun setDeviceInfo() {
        mDevice?.let { device ->

            if (device.gameName == null) {
                sendMessage("设置设备信息时：游戏获取错误！")
                return
            }

            // 1. 构造调用commonFunction的请求参数
            val haimaMiddlewareBean = HaimaMiddlewareBean().apply {
                methodName = "setDeviceInfo"
                info = device
            }

            // 2. 将请求参数转为json字符串并通过aidl调用
            val gson = Gson()
            val result = middlewareRequest?.commonFunction(gson.toJson(haimaMiddlewareBean))

            // 3.处理返回的结果
            result?.let {
                val response = gson.fromJson(it, HaimaMiddlewareResponse::class.java)
                val success = response.result == 1
                Log.i(TAG, "设置设备信息 success：$success")

                if (success) {
                    // 4.成功了，应该告诉客户端
                    sendMessage("设置设备信息成功：DeviceInfo：${device}")
                } else {
                    sendMessage("设置设备信息失败：${response.errorMsg}")
                }
            } ?: sendMessage("设置设备信息时，设备信息异常")
        }
    }

    /**
     * 通过commonFunction获取设备信息
     */
    @SuppressLint("SetTextI18n")
    @Throws(RemoteException::class, JSONException::class)
    private fun getDeviceInfo() {
        val isInCloud = MessageSDK.getInstance().isRunningCloud
        if (isInCloud) {
            val haimaMiddlewareBean = HaimaMiddlewareBean()
            haimaMiddlewareBean.methodName = "getDeviceInfo"

            // 1.调用commonFunction获取设备信息
            val gson = Gson()
            val result = middlewareRequest?.commonFunction(gson.toJson(haimaMiddlewareBean))
            if (result != null) {
                val response = gson.fromJson(
                    result,
                    HaimaMiddlewareResponse::class.java
                )
                // 若result==1则说明获取设备信息成功
                if (response.result == 1) {
                    // 直接将successMsg反序列化为DeviceInfo对象
                    val deviceInfo = gson.fromJson(
                        response.successMsg,
                        DeviceInfo::class.java
                    )
                    Log.d(TAG, "deviceInfo=$deviceInfo")

                    // 默认一个游戏，为了可以正常的进行授权操作
                    deviceInfo.gameName = mAccount?.data?.gameName ?: "王者荣耀"

                    sendMessage("获取云手机设备信息成功：DeviceInfo：${deviceInfo}")

                    this.mDevice = deviceInfo
                }
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()

        // 取消绑定服务
        if (mIsBound) {
            unbindService(connection)
            mIsBound = false
        }

        // 注销SDK
        unInitMessageSDK()

        // 销毁播放器
        videoPlayer?.release()

        println("定时器已销毁")
    }

    override fun onPause() {
        super.onPause()
        videoPlayer?.onVideoPause()
    }

    override fun onResume() {
        super.onResume()
        videoPlayer?.onVideoResume()
        // 隐藏
        YUtils.hideLoading()
    }

}
